#include "DeviceYclHelper.h"

#include <QDebug>

#include "ConstNames.h"
#include "ModbusManager.h"

#define REG_PRESSURE 100            // 压力(浮点数)
#define REG_SYSTEM_STATE 102        // 系统状态(枚举)
#define REG_SYSTEM_SUB_STATE 103    // 子状态(枚举)
#define REG_SYSTEM_READY 104        // 系统准备就绪(bool)
#define REG_SYSTEM_ERROR 180        // 系统错误(u16)
#define REG_DRAW_WATER_TIMEOUT 200  // 抽水超时时间(秒)
#define REG_UPPER_WATER_TIME 201    // 配水时间(秒)
#define REG_EMPTY_WATER_TIME 202    // 排空时间(秒)
#define REG_CLEAN_WATER_TIME 203    // 清洗时间(秒)
#define REG_CLEAN_ALGAE_TIME 204    // 除藻时间(秒)
#define REG_DRAW_ALGAE_TIME 205     // 抽除藻剂时间(秒)
#define REG_SETTLE_TIME 206         // 沉淀时间(秒)
#define REG_DRAW_MODE 207           // 抽水模式 (enum)

#define REG_YCL_CONTROL 1010
typedef enum {
    CMD_STEP_DRAW_WATER = 100,   // 单步抽水
    CMD_STEP_UPPER_WATER,        // 单步配水
    CMD_STEP_EMPTY_WATER,        // 单步排空
    CMD_STEP_CLEAN,              // 单步清洗
    CMD_STEP_CLEAN_ALGAE,        // 抽除藻剂
    CMD_START_CLEAN_ALGAE,       // 除藻启动
    CMD_START_NORMAL,            // 常规启动
    CMD_STOP_ALL,                // 停止所有
    CMD_STEP_SPIKE_VALVE_OPEN,   // 开加标阀
    CMD_STEP_SPIKE_VALVE_CLOSE,  // 关加标阀
} ycl_cmd_t;
static const QMap<QString, quint16> YCL_OPERATE_MAP = {
    {OperationNames::PRE_STEP_DRAW_WATER, CMD_STEP_DRAW_WATER},
    {OperationNames::PRE_STEP_UPPER_WATER, CMD_STEP_UPPER_WATER},
    {OperationNames::PRE_STEP_EMPTY_WATER, CMD_STEP_EMPTY_WATER},
    {OperationNames::PRE_STEP_CLEAN, CMD_STEP_CLEAN},
    {OperationNames::PRE_STEP_ALGAE_REMOVAL, CMD_STEP_CLEAN_ALGAE},
    {OperationNames::PRE_ALGAE_REMOVAL, CMD_START_CLEAN_ALGAE},
    {OperationNames::PRE_PROCESS, CMD_START_NORMAL},
    {OperationNames::COMMON_STOP, CMD_STOP_ALL},
    {OperationNames::PRE_STEP_SPIKE_VALVE_OPEN, CMD_STEP_SPIKE_VALVE_OPEN},
    {OperationNames::PRE_STEP_SPIKE_VALVE_CLOSE, CMD_STEP_SPIKE_VALVE_CLOSE},
};

static const QMap<quint16, QString> YCL_STEP_STATE_MAP = {
    {VALVE_OP_IDLE, StateNames::PRE_STATE_IDLE},
    {VALVE_OP_DRAW_WATER, StateNames::PRE_STATE_DRAW_WATER},
    {VALVE_OP_UPPER_WATER, StateNames::PRE_STATE_UPPER_WATER},
    {VALVE_OP_EMPTY_WATER, StateNames::PRE_STATE_EMPTY_WATER},
    {VALVE_OP_CLEAN, StateNames::PRE_STATE_CLEAN},
    {VALVE_OP_CLEAN_ALGAE, StateNames::PRE_STATE_ALGAE_REMOVAL},
    {VALVE_OP_SETTLE, StateNames::PRE_STATE_SETTLE},
};
// 主状态定义
typedef enum {
    STATE_IDLE = 0,
    STATE_RUNNING,       // 启动流程进行中
    STATE_STEP_RUNNING,  // 单步流程进行中
    STATE_CLEAN_ALGAE,   // 除藻流程进行中
    STATE_STOPPING,      // 正在停止
} ycl_state_t;
typedef enum {
    ERROR_NONE = 0x0000,           // 无错误
    ERROR_EMPTY_WATER = 0x0001,    // 排空错误
    ERROR_CLEAN = 0x0002,          // 清洗错误
    ERROR_WATER_PUMP = 0x0003,     // 抽水错误
    ERROR_WATER_MIX = 0x0004,      // 配水错误
    ERROR_ALGAE_REMOVAL = 0x0005,  // 除藻错误
    ERROR_OTHER = 0x0006,          // 其他错误
} ycl_error_type_t;
static const QMap<quint16, QString> YCL_ERROR_TYPE_MAP = {
    {ERROR_NONE, ErrorNames::COMMON_ERROR_NONE},
    {ERROR_EMPTY_WATER, ErrorNames::PRE_ERROR_EMPTY_WATER},
    {ERROR_CLEAN, ErrorNames::PRE_ERROR_CLEAN},
    {ERROR_WATER_PUMP, ErrorNames::PRE_ERROR_WATER_PUMP},
    {ERROR_WATER_MIX, ErrorNames::PRE_ERROR_WATER_MIX},
    {ERROR_ALGAE_REMOVAL, ErrorNames::PRE_ERROR_ALGAE_REMOVAL},
    {ERROR_OTHER, ErrorNames::PRE_ERROR_OTHER},
};
/* 配置项名称映射 */
static const QVariantMap DEVICE_CONFIG_MAP = {
    {ConfigNames::PRE_CONFIG_DRAW_WATER_TIME, 30},      // 抽水时间
    {ConfigNames::PRE_CONFIG_UPPER_WATER_TIME, 20},     // 配水时间
    {ConfigNames::PRE_CONFIG_EMPTY_WATER_TIME, 15},     // 排空时间
    {ConfigNames::PRE_CONFIG_CLEAN_WATER_TIME, 10},     // 清洗时间
    {ConfigNames::PRE_CONFIG_CLEAN_ALGAE_TIME, 5},      // 除藻时间
    {ConfigNames::PRE_CONFIG_DRAW_ALGAE_TIME, 5},       // 抽除藻剂时间
    {ConfigNames::PRE_CONFIG_SETTLE_TIME, 60},          // 沉淀时间
    {ConfigNames::PRE_CONFIG_DRAIN_PUMP_SELECTION, 1},  // 抽水泵选择
};
DeviceYclHelper::DeviceYclHelper(QString deviceName, QObject* parent) : IDevice(deviceName, parent)
{
    m_operateMap = YCL_OPERATE_MAP;
    m_statusMap = YCL_STEP_STATE_MAP;
    m_errorMap = YCL_ERROR_TYPE_MAP;
    m_configMap = DEVICE_CONFIG_MAP;
    qDebug() << "initialized with device name:" << m_deviceName;
}

DeviceYclHelper::~DeviceYclHelper() { qDebug() << "destroyed for device name:" << m_deviceName; }

void DeviceYclHelper::control(quint16 optCode) { IDevice::control(REG_YCL_CONTROL, optCode); }
void DeviceYclHelper::onGetDeviceData()
{
    if (m_busyFlags.dataBusy) {
        return;
    }
    m_busyFlags.dataBusy = true;

    ModbusHelper* modbus = ModbusManager::instance()->getModbusHelper(m_deviceName);
    if (!modbus) {
        qDebug() << "Failed to get ModbusHelper for device:" << m_deviceName;
        m_busyFlags.dataBusy = false;
        return;
    }
    modbus->asyncRead(1, 32)
        .then([this, modbus](const QVector<quint16>& result) {
            m_deviceData.valveStatus.clear();
            m_deviceData.valveStatus = result;
            return modbus->asyncReadFloat(REG_PRESSURE, 1);
        })
        .then([this, modbus](const QVector<float>& result) {
            m_deviceData.pressure_lastResult = result[0];
            return modbus->asyncRead(REG_SYSTEM_STATE, 2);
        })
        .then([this, modbus](const QVector<quint16>& result) {
            m_deviceData.status = result[0];
            m_isIdle = m_deviceData.status == STATE_IDLE;  // 更新空闲状态
            m_deviceData.ycl_step_state = result[1];
            return modbus->asyncRead(REG_SYSTEM_ERROR, 1);
        })
        .then([this, modbus](const QVector<quint16>& result) {
            m_deviceData.faultCode = result[0];
            if (m_deviceData.faultCode != m_lastFaultCode && m_deviceData.faultCode != ERROR_NONE) {
                emit errorOccurred(QString("错误: %1").arg(getErrorName(m_deviceData.faultCode)));
            }
            m_lastFaultCode = m_deviceData.faultCode;
            emit deviceDataChanged(m_deviceData);
            return modbus->asyncRead(REG_DRAW_WATER_TIMEOUT, 8);
        })
        .then([this, modbus](const QVector<quint16>& result) {
            m_configMap[ConfigNames::PRE_CONFIG_DRAW_WATER_TIME] = result[0];
            m_configMap[ConfigNames::PRE_CONFIG_UPPER_WATER_TIME] = result[1];
            m_configMap[ConfigNames::PRE_CONFIG_EMPTY_WATER_TIME] = result[2];
            m_configMap[ConfigNames::PRE_CONFIG_CLEAN_WATER_TIME] = result[3];
            m_configMap[ConfigNames::PRE_CONFIG_CLEAN_ALGAE_TIME] = result[4];
            m_configMap[ConfigNames::PRE_CONFIG_DRAW_ALGAE_TIME] = result[5];
            m_configMap[ConfigNames::PRE_CONFIG_SETTLE_TIME] = result[6];
            m_configMap[ConfigNames::PRE_CONFIG_DRAIN_PUMP_SELECTION] = result[7];
        })
        .finally([this]() { m_busyFlags.dataBusy = false; });
}

bool DeviceYclHelper::saveDeviceConfig(const QVariantMap& configMap)
{
    if (m_busyFlags.controlBusy) {
        return false;
    }
    m_busyFlags.controlBusy = true;
    ModbusHelper* modbus = ModbusManager::instance()->getModbusHelper(m_deviceName);
    if (!modbus) {
        qDebug() << "Failed to get ModbusHelper for device:" << m_deviceName;
        m_busyFlags.controlBusy = false;
        return false;
    }
    QVector<quint16> _data;
    _data << configMap[ConfigNames::PRE_CONFIG_DRAW_WATER_TIME].toUInt();
    _data << configMap[ConfigNames::PRE_CONFIG_UPPER_WATER_TIME].toUInt();
    _data << configMap[ConfigNames::PRE_CONFIG_EMPTY_WATER_TIME].toUInt();
    _data << configMap[ConfigNames::PRE_CONFIG_CLEAN_WATER_TIME].toUInt();
    _data << configMap[ConfigNames::PRE_CONFIG_CLEAN_ALGAE_TIME].toUInt();
    _data << configMap[ConfigNames::PRE_CONFIG_DRAW_ALGAE_TIME].toUInt();
    _data << configMap[ConfigNames::PRE_CONFIG_SETTLE_TIME].toUInt();
    _data << configMap[ConfigNames::PRE_CONFIG_DRAIN_PUMP_SELECTION].toUInt();
    modbus->asyncWrite(REG_DRAW_WATER_TIMEOUT, _data)
        .fail([this](const QString& error) {
            qDebug() << "Failed to write register for device:" << m_deviceName << "Error:" << error;
        })
        .finally([this]() { m_busyFlags.controlBusy = false; });
    return true;
}
